package unimelb.distSystems.project2;

import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import unimelb.distSystems.communications.CORBA.ServiceMatchRoom;
import unimelb.distSystems.communications.CORBA.ServicePlayer;

/*
 * Subclass of GUIScreen where player looks to join a match room or host new
 * match room or log out
 */
public class MenuScreen extends GUIScreen{
	/*
	 * GUI components
	 */
	private JButton search_button = new JButton("Search");
	private JButton getall_button = new JButton("Get all of match rooms");
	private JButton host_button = new JButton("Host a new match room");
	private JButton join_button = new JButton("Join the selected room");
	private JButton logout_button = new JButton("Log out");
	private DefaultListModel matchroom_textlist = new DefaultListModel();
	private JList matchroom_list_container = new JList(matchroom_textlist);
	private JLabel match_room_text = new JLabel("List of match rooms on the server");
	private JLabel search_text = new JLabel("Words to search");
	private JTextField search_tf = new JTextField(15);
	private JLabel title_text = new JLabel("Match rooms on the server");
	private JLabel drivername_text = new JLabel("");
	private JLabel statistic_text=new JLabel("Statistics:");
	private JTextArea statistic_ta = new JTextArea();
	private ImagePanel avatar = new ImagePanel(null);
	
	//Variables
	private Game client=null;
	private Player current_player=null;
	private LinkedList<MatchRoom> returned_list;
	
	/*
	 * Constructor
	 */
	public MenuScreen(Game client)
	{
		super();
		this.client=client;
		initialise_listeners(client);
		
		matchroom_list_container.setFont(new Font(null,Font.BOLD,14));
		title_text.setFont(new Font(null,Font.BOLD,30));
		search_tf.setPreferredSize(new Dimension(260,30));
		statistic_ta.setBackground(null);
		statistic_ta.setEditable(false);
	}
	
	/*
	 * @see unimelb.distSystems.project2.GUIScreen#perform_actions_prior_display()
	 */
	public void perform_actions_prior_display()
	{
		matchroom_textlist.removeAllElements();
		search_tf.setText("");
		join_button.setEnabled(false);
		
		current_player =  client.get_current_player();
		statistic_ta.setText("0 Wins\n0 Losses\netc");
		drivername_text.setText(current_player.getDriverName());
	}
	
	/*
	 * @see unimelb.distSystems.project2.GUIScreen#perform_actions_prior_exit()
	 */
	public void perform_actions_prior_exit()
	{
		//Do nothing
	}

	/*
	 * @see unimelb.distSystems.project2.GUIScreen#display(java.awt.Container)
	 */
	public void display(Container screen_container) {
		GridBagConstraints c = new GridBagConstraints();
		c.fill = GridBagConstraints.HORIZONTAL;
		screen_container.setLayout(new FlowLayout());
		
		JPanel title_p = new JPanel();
		title_p.setLayout(new GridBagLayout());
		title_p.add(title_text);
		screen_container.add(title_p);
		
		JPanel main_p = new JPanel();
		main_p.setLayout(new GridBagLayout());
		screen_container.add(main_p);
		
		JPanel left_column_p = new JPanel();
		left_column_p.setLayout(new GridBagLayout());
		c.gridx = 0;
		c.gridy = 0;
		main_p.add(left_column_p,c);
		
		c.gridx = 0;
		c.gridy = 0;
		left_column_p.add(match_room_text,c);
		
		JScrollPane matchroom_scrollp = new JScrollPane(matchroom_list_container);
		c.gridx = 0;
		c.gridy = 1;
		c.ipady=250;
		c.ipadx=150;
		left_column_p.add(matchroom_scrollp,c);
		c.ipady=1;
		c.ipadx=1;
		
		c.gridx = 0;
		c.gridy = 2;
		left_column_p.add(blank,c);
		
		c.gridx = 0;
		c.gridy = 3;
		left_column_p.add(logout_button,c);
		
		JPanel right_column_p = new JPanel();
		right_column_p.setLayout(new GridBagLayout());
		c.gridx = 1;
		c.gridy = 0;
		c.insets=new Insets(0,20,0,0);
		main_p.add(right_column_p,c);
		
		c.gridx = 0;
		c.gridy = 0;
		right_column_p.add(search_text,c);
		
		c.gridx = 0;
		c.gridy = 1;
		right_column_p.add(search_tf,c);
		
		c.gridx = 0;
		c.gridy = 2;
		right_column_p.add(search_button,c);
		
		c.gridx = 0;
		c.gridy = 3;
		right_column_p.add(getall_button,c);
		
		c.gridx = 0;
		c.gridy = 4;
		right_column_p.add(blank2,c);
				
		c.gridx = 0;
		c.gridy = 5;
		right_column_p.add(join_button,c);
		
		c.gridx = 0;
		c.gridy = 6;
		right_column_p.add(host_button,c);
		
		c.gridx = 0;
		c.gridy = 7;
		right_column_p.add(blank3,c);
		
		JPanel player_info_p = new JPanel();
		player_info_p.setBorder(BorderFactory.createTitledBorder("Your driver profile"));
		player_info_p.setLayout(new GridBagLayout());
		c.gridx = 0;
		c.gridy = 8;
		right_column_p.add(player_info_p,c);
		
		c.insets=new Insets(0,0,0,0);
		c.gridx = 0;
		c.gridy = 0;
		player_info_p.add(drivername_text,c);
		
		avatar.load_new_image(current_player.getAvatar());
		c.gridx = 0;
		c.gridy = 1;
		c.ipadx=avatar.getImageWidth();
		c.ipady=avatar.getImageHeight();
		player_info_p.add(avatar,c);
		c.ipadx=1;
		c.ipady=1;
		
		c.gridx = 0;
		c.gridy = 2;
		player_info_p.add(statistic_text,c);
		
		c.gridx = 0;
		c.gridy = 3;
		player_info_p.add(statistic_ta,c);
	}

	/*
	 * @see unimelb.distSystems.project2.GUIScreen#initialise_listeners(unimelb.distSystems.project2.Game)
	 */
	protected void initialise_listeners(final Game client) {
		/*
		 * Log out and clear the cache of player instance
		 */
		logout_button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				client.cache_player(null);
				client.go_to_screen(Game.LOGIN_SCREEN);
			}
		});
				
		/*
		 * Allow joining if match room is selected
		 * or prevent joining if match room is not selected
		 */
		matchroom_list_container.addListSelectionListener(new ListSelectionListener() {
			public void valueChanged(ListSelectionEvent evt) {
				if(matchroom_list_container.getSelectedIndex()>=0)
					join_button.setEnabled(true);
				else
					join_button.setEnabled(false);
			}
		});
		
		/*
		 * Search for particular match room with name
		 */
		search_button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				////////////////////////////////////
				//COBRA COMMUNICATION
				////////////////////////////////////
				//Pass words to GameServer
				//Get matched match room list from GameServer
				List list = Arrays.asList(client.getGameService().searchRoom(search_tf.getText()));
                LinkedList<MatchRoom> returned_list = fillup(list);
				load_into_matchroom_textlist(returned_list);
			}
		});
		
		/*
		 * Go to another screen to host new match room
		 */
		host_button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				client.go_to_screen(Game.HOST_SCREEN);
			}
		});
		
		/*
		 * Load all match rooms on the server
		 */
		getall_button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				////////////////////////////////////
				//COBRA COMMUNICATION
				////////////////////////////////////
				//Get latest copy of match room list from GameServer
				List list = Arrays.asList(client.getGameService().getAllRooms());
				LinkedList<MatchRoom> returned_list = fillup(list);
				load_into_matchroom_textlist(returned_list);
			}
		});
		
		/*
		 * Join the selected match room
		 */
		join_button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				ListItem selected = (ListItem)matchroom_textlist.get(matchroom_list_container.getSelectedIndex());
				long matchroom_id=selected.getID();
				
				////////////////////////////////////
				//COBRA COMMUNICATION
				////////////////////////////////////
				//Get match room object from GameServer based on ID
				ServicePlayer[] players = client.getGameService().getPlayers(matchroom_id);
                ServiceMatchRoom sRoom = client.getGameService().getMatchRoom(matchroom_id);
                MatchRoom this_room = new MatchRoom(sRoom);
				
				if(sRoom==null)
					JOptionPane.showMessageDialog(null,"This match room you attempted to join is no longer hosted now.",
							"Error",JOptionPane.WARNING_MESSAGE);
				else if(this_room.isInRacingProgress())
					JOptionPane.showMessageDialog(null,"This match room you attempted to join is in racing progress now. Try it later.",
							"Error",JOptionPane.WARNING_MESSAGE);
				else if(this_room.getMaxPlayers()<=players.length)
					JOptionPane.showMessageDialog(null,"This match room you attempted to join is full now. Try it later.",
							"Error",JOptionPane.WARNING_MESSAGE);
				else
				{
					////////////////////////////////////
					//COBRA COMMUNICATION
					////////////////////////////////////
					//Invoke join() on the server
					client.getGameService().joinGame(matchroom_id, current_player.getPlayerID());
					client.cache_match_room(this_room);
					client.go_to_screen(Game.MATCHROOM_SCREEN);
				}
			}
		});
	}
	
	private LinkedList<MatchRoom> fillup(List list)
	{
            LinkedList<MatchRoom> l = new LinkedList<MatchRoom>();
            Iterator it = list.iterator();

            while(it.hasNext()){
                ServiceMatchRoom sRoom = (ServiceMatchRoom)it.next();
                l.add(new MatchRoom(sRoom));
            }
            return l;
	}
	
	/*
	 * Load list of match rooms into GUI list component
	 * Input: List of match rooms (or empty list)
	 * Output: Nothing
	 */
	private void load_into_matchroom_textlist(LinkedList<MatchRoom> matchroom_list)
	{
		matchroom_textlist.removeAllElements();
		
		Iterator<MatchRoom> itr = matchroom_list.iterator();
		while(itr.hasNext())
		{
			MatchRoom this_matchroom = itr.next();
			String text="";
			
			////////////////////////////////////
			//COBRA COMMUNICATION
			////////////////////////////////////
			ServicePlayer[] players = client.getGameService().getPlayers(this_matchroom.getMatchRoomID());
			
			if(this_matchroom.isInRacingProgress())
				text+="[ RACING ] ";
			else if(players.length==this_matchroom.getMaxPlayers())
				text+="[   FULL   ] ";
			else
				text+="[   OPEN   ] ";
			
			text+="("+players.length+"/"+this_matchroom.getMaxPlayers()+") ";
			text+=this_matchroom.getMatchRoomName();
			
			ListItem item = new ListItem(this_matchroom.getMatchRoomID(),text);
			matchroom_textlist.addElement(item);
		}
	}
}
